package com.bcgtgjyb.huanwen.customview.mylibrary.spring;

import com.bcgtgjyb.huanwen.customview.mylibrary.ResourceTable;
import com.bcgtgjyb.huanwen.customview.mylibrary.tool.ScreenUtil;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by bigwen on 2016/4/25.
 */
public class GameMap extends Component implements Component.DrawTask, Component.BindStateChangedListener {
    private static final int FIVE = 5;
    private static final int TWENTY = -20;
    private static final int TWO = 2;
    private static final int TEN = 10;
    private static final int ELEVEN = 11;
    private static final int TWLVE = 12;
    private static final int THIRTEEN = 13;
    private static final int THREE = 3;
    private static final int FOUR = 4;
    private static final int SIX = 6;
    private static final int SEVEN = 7;
    private static final int EIGHT = 8;
    private static final int NINE = 9;
    private static final int ZERO = 0;
    private static final int FOURTEEN = 14;
    private static final int FIFTEEN = 15;
    private static final int FORTY = 40;
    private static final int ONEHUNDRED = 100;
    private static final int SIXTEEN = 16;
    private Context mContext;
    private int mapW,mapH,screenW,screenH;
    private PixelMap bitmap;
    private Paint mPaint;
    private int dd;
    private SecureRandom random = new SecureRandom();
    private List<Point> randomPoints = new ArrayList<>();
    private int scale = 0;
    private float nowScale = 1;
    private Thread mThread;
    private boolean isPlay = false;
    private SpringCallback springCallback = null;
    private float tx = 0,ty = 0;
    private List<Point> removePoint = new ArrayList<>();
    private float degree = 0;
    private float width;

    /**
     * GameMap 构造方法
     *
     * @param context 上下文
     */

    public GameMap(Context context) {
        super(context);
        mContext = context;
        init();
    }

    /**
     * 构造方法GameMap
     *
     * @param context 上下文
     * @param attrs 属性
     */
    public GameMap(Context context, AttrSet attrs) {
        super(context, attrs);
        mContext = context;
        init();
    }

    private void init() {
        addDrawTask(this);
        setBindStateChangedListener(this);
        scale = ScreenUtil.getScreenWidth(mContext) / FIVE;
        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(ScreenUtil.dip2px(mContext, FIVE));
        dd = ScreenUtil.dip2px(mContext, 1);
        screenW = ScreenUtil.getScreenWidth(mContext);
        screenH = ScreenUtil.getScreenHeight(mContext);
        width = ScreenUtil.dip2px(mContext, TEN);
        bitmap =
                getPixelMap(getContext(), ResourceTable.Media_ic_launcher);
        mapW = bitmap.getImageInfo().size.width;
        mapH = bitmap.getImageInfo().size.height;

        int nn = screenW / mapW;
        int mm = screenH / mapH;

        int startX = TWENTY * mapW, startY = TWENTY * mapH;
        for (int ii = 0; ii < (nn + FORTY); ii++) {
            for (int jj = 0; jj < (mm + FORTY); jj++) {
                startY += mapH;
            }
            startX += mapW;
            startY = TWENTY * mapH;
        }
        initThread();
        addRandomPoint(ONEHUNDRED);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        canvas.translate(tx, ty);
        if (scale < width) {
            float scalePamra = width / scale;
            canvas.scale((float) 1d / scalePamra, (float)1d / scalePamra, (float) ((double)screenW / TWO), (float) ((double)screenH / TWO));
            if (springCallback != null) {
                springCallback.canvasScale((float)1d / scalePamra);
            }
            nowScale = (float) (1d / scalePamra);
        }

        float sw = width / TWO * nowScale;
        float sh = width / TWO * nowScale;
        for (Point point : randomPoints) {
            float xx = point.getPointX() + tx;
            float yy = point.getPointY() + ty;
            if ((xx >= (screenW / 2d - sw) && xx <= (screenW / 2d + sw))
                    &&
                    (yy >= (screenH / 2d - sh) && yy <= (screenH / 2d + sh))) {
                removePoint.add(point);
                if (springCallback != null) {
                    springCallback.changePoint();
                }
            } else {
                canvas.drawPoint(point.getPointX(), point.getPointY(), mPaint);
            }
        }
        if (removePoint.size() != 0) {
            int numb = removePoint.size();
            randomPoints.removeAll(removePoint);
            removePoint.clear();
            addRandomPoint(numb);
        }
    }

    private void addRandomPoint(int param) {
        for (int ii = 0; ii < param; ii++) {
            Point point = new Point();
            int kk = random.nextBoolean() ? 1 : -1;
            int ks = random.nextBoolean() ? 1 : -1;
            point.modify(kk * random.nextInt(FIVE * mapW), ks * random.nextInt(FIVE * mapH));
            randomPoints.add(point);
        }
    }

    /**
     * translateCanvas 方法
     *
     * @param xx x轴
     * @param xy y轴
     */
    public void translateCanvas(float xx, float xy) {
        tx = tx + xx;
        ty = ty + xy;
        invalidate();
    }

    /**
     * 移动
     *
     * @param dv 值
     */
    public void move(double dv) {
        float pi = (float) Math.PI;
        if (dv < 0) {
            dv = dv + pi * TWO;
        }
        float unit = 0.125f * pi;
        if (dv > FIFTEEN * unit || dv < unit) {
            this.degree = ZERO;
        } else if (dv > unit && dv < THREE * unit) {
            this.degree = TWO * unit;
        } else if (dv > THREE * unit && dv < FIVE * unit) {
            this.degree = FOUR * unit;
        } else if (dv > FIVE * unit && dv < SEVEN * unit) {
            this.degree = SIX * unit;
        } else if (dv > SEVEN * unit && dv < NINE * unit) {
            this.degree = EIGHT * unit;
        } else if (dv > NINE * unit && dv < ELEVEN * unit) {
            this.degree = TEN * unit;
        } else if (dv > ELEVEN * unit && dv < THIRTEEN * unit) {
            this.degree = TWLVE * unit;
        } else if (dv > THIRTEEN * unit && dv < FIFTEEN * unit) {
            this.degree = FOURTEEN * unit;
        }
    }

    public float getDegree() {
        return degree;
    }

    private void initThread() {
        mThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (isPlay) {
                    float x1 = -(float) (Math.cos(getDegree()) * dd);
                    float y1 = -(float) (Math.sin(getDegree()) * dd);
                    translateCanvas(x1, y1);
                    try {
                        Thread.sleep(SIXTEEN);
                    } catch (InterruptedException e) {
                    }
                }
            }
        });
    }

    /**
     * 开始
     *
     */
    public void start() {
        isPlay = true;
        mThread.start();
    }

    /**
     * 停止
     *
     */
    public void stop() {
        isPlay = false;
    }
    /**
     * getPixelMap 方法
     *
     * @param context 上下文
     * @param drawableId 可绘制的ID
     * @return 0
     */

    public static PixelMap getPixelMap(Context context, int drawableId) {
        InputStream drawableInputStream = null;
        try {
            drawableInputStream = context.getResourceManager().getResource(drawableId);
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = "image/png";
            ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
            decodingOptions.desiredSize = new Size(0, 0);
            ImageSource imageSource = ImageSource.create(drawableInputStream, sourceOptions);
            decodingOptions.desiredRegion = new Rect(0, 0, 0, 0);
            decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
            PixelMap pixelMap = imageSource.createPixelmap(decodingOptions);
            return pixelMap;
        } catch (IOException | NotExistException e) {
        } finally {
            try {
                if (drawableInputStream != null) {
                    drawableInputStream.close();
                }
            } catch (IOException e) {
            }
        }
        return null;
    }

    @Override
    public boolean isBoundToWindow() {
        return super.isBoundToWindow();
    }

    @Override
    public void onComponentBoundToWindow(Component component) {
        start();
    }

    @Override
    public void onComponentUnboundFromWindow(Component component) {
        stop();
    }

    public void setSpringCallback(SpringCallback springCallback) {
        this.springCallback = springCallback;
    }

    /**
     * SpringCallback 接口
     */
    public interface SpringCallback {
        /**
         * 变更点
         *
         */
        void changePoint();

        /**
         * 画布比例
         *
         * @param parma
         */
        void canvasScale(float parma);
    }
}
